import decimal
import json
import re
from datetime import datetime
from decimal import Decimal

import requests

from inventory.models import Material
from utils.enums import SCE
from utils.exceptions import BusinessException
from utils.tools import CarType, POUND_LIST_STATE, car_type_dict


# 获取用户token
def req_login() -> str:
    url = "http://192.168.2.45:8066/trade/user/login"

    payload = {
        "username": "clcdl",
        "password": "MTIzNDU2",
        "loginTime": f"{datetime.today().isoformat()}"
    }
    headers = {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br",
        "User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0",
        "Connection": "keep-alive",
        "Content-Type": "application/json"
    }
    try:
        response = requests.request("POST", url, json=payload, headers=headers)
        token = json.loads(response.text)['data']['token']
        return token
    except OSError:
        raise BusinessException(SCE.no_enum, f'无法连接景智系统')
    except TypeError:
        raise BusinessException(SCE.no_enum, f'向景智系统请求登录权限被拒绝')


# 获取检斤单列表的一页
def req_checklist_list(token: str, car_type_id: CarType, time_range: tuple[str, str], state: POUND_LIST_STATE,
                       page_nm: int):
    url = "http://192.168.2.45:8067/trade/trucking/listJjdTruckingOrder"
    payload = {
        "name": "",
        "time": [
            time_range[0],
            time_range[1]
        ],
        "carTypeId": car_type_id,
        "closed": state,
        "pageNum": page_nm,
        "pageSize": 50,
        "pageSizes": [
            10,
            20,
            30,
            50
        ],
        "total": 0,
        "checkTag": 2,
        "carNo": "",
        "startDate": f"{time_range[0]}" + ' ' + '00:00:00',
        "endDate": f"{time_range[1]}" + ' ' + "23:59:59"
    }
    headers = {
        "Token": token,
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br",
        "User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0",
        "Connection": "keep-alive",
        "Content-Type": "application/json"
    }
    try:
        response = requests.request("POST", url, json=payload, headers=headers)
        data = json.loads(response.text)
        return data
    except OSError:
        return False


# 获取检斤单详情
def req_checklist_list_detail(token: str, check_list_id: str):
    url = "http://192.168.2.45:8067/trade/trucking/listJjdTruckingOrder"
    payload = {
        "id": check_list_id
    }
    headers = {
        "Token": token,
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br",
        "User-Agent": "PostmanRuntime-ApipostRuntime/1.1.0",
        "Connection": "keep-alive",
        "Content-Type": "application/json"
    }
    try:
        response = requests.request("POST", url, json=payload, headers=headers)
        data = json.loads(response.text)
        return data
    except OSError:
        return False


# 根据编码确认型号
# data: []
def code_to_material_id(data: list[dict]):
    code_list = []
    for i in data:
        code_list.append(i['code'])
    temp1 = Material.objects.filter(code__in=code_list).values('code', 'id')  # 无需去重，__in会自动去的
    code_dict = {}  # {'4067': 123, '4068': 124 ... }
    for j in temp1:
        code_dict[j['code']] = j['id']
    for k in data:
        if k['code'] in code_dict:
            k['material_id'] = code_dict[k['code']]
        else:
            data.remove(k)
    return data


# 获取全部信息，并按照前端标准入库格式返回
def req_all_checklist(car_type_id: CarType, time_range: tuple[str, str], state: POUND_LIST_STATE):
    # 获取token
    token = req_login()
    # 获取检斤单列表
    sys_id_list: list[str] = []
    page_1 = req_checklist_list(token, car_type_id, time_range, state, 1)
    for i in page_1['data']['list']:
        sys_id_list.append(i['sysId'])

    if page_1['data']['total'] > 500:
        raise BusinessException(SCE.no_enum, f'所导入车辆数超过200，请重新选择日期')

    # 检斤单页面每一页的最大页码是五十
    if page_1['data']['total'] > 50:
        temp1 = page_1['data']['total'] // 50
        temp2 = page_1['data']['total'] % 50
        if temp2 == 0:
            temp1 -= 1
        for j in range(temp1):
            temp3 = req_checklist_list(token, car_type_id, time_range, state, j + 2)
            for k in temp3['data']['list']:
                sys_id_list.append(k['sysId'])
    result = []
    # 判断是角钢还是带钢
    if car_type_dict['带钢'] == car_type_id:
        for m in sys_id_list:  # m 指的是
            temp4 = req_checklist_list_detail(token, m)
            remark = f"{temp4['data']['master']['customerName']}，{temp4['data']['master']['carno']}，{temp4['data']['master']['billno']}"
            # 带钢没有匹重，需要自己匹
            result_temp = []
            j_weight: Decimal = Decimal(temp4['data']['master']['netWeight']).quantize(Decimal('0.001'))  # 净重
            if len(temp4['data']['detail']) > 1:  # 如果规格不止一条，进行匹重
                total_whole_piece = 0  # 总件数
                temp_1 = 0  # 最薄的那件货，下标是第几
                temp_2 = Decimal('100')  # 最薄的厚度
                for index, n in enumerate(temp4['data']['detail']):
                    total_whole_piece += n['wholepiece']
                    thickness = Decimal(re.split(r'[*|x|X]', n['specification'])[1])
                    if thickness < temp_2:
                        temp_2 = thickness
                        temp_1 = index
                    result_temp.append({
                        'code': n['number'],
                        'whole_piece': n['wholepiece'],
                        'scatt_piece': n['scattpiece'],
                        'model': n['specification'],
                        'weight': 0,
                        'name': n['materialidName'],
                        'remark': remark
                    })
                # 单件重量
                piece_weight = Decimal(str(j_weight / total_whole_piece)).quantize(Decimal('0.001'), rounding=decimal.ROUND_DOWN)
                # 较厚的带钢重量赋值
                temp_3 = Decimal(0)  # 目前的累计重量
                for index, i in enumerate(result_temp):
                    if index != temp_1:
                        i['weight'] = Decimal(str((piece_weight * i['whole_piece']) / 1000)).quantize(Decimal('0.001'), rounding=decimal.ROUND_DOWN)
                        temp_3 += i['weight']
                # 较薄的带钢重量赋值
                result_temp[temp_1]['weight'] = Decimal(str((j_weight - temp_3*1000) / 1000)).quantize(Decimal('0.001'))
            else:  # 就一条，那就不需要匹重
                for n in temp4['data']['detail']:
                    result_temp.append({
                        'code': n['number'],
                        'whole_piece': n['wholepiece'],
                        'scatt_piece': n['scattpiece'],
                        'model': n['specification'],
                        'weight': j_weight / 1000,
                        'name': n['materialidName'],
                        'remark': remark
                    })
            result += result_temp
        result = list(reversed(result))  # 倒置数组，因为默认排序是时间倒序列
        result = code_to_material_id(result)
        return result, page_1['data']['total']
    elif car_type_dict['角钢'] == car_type_id:  # 角钢额其他品种，待开发
        for m in sys_id_list:
            temp4 = req_checklist_list_detail(token, m)
            remark = f"{temp4['data']['master']['customerName']}，{temp4['data']['master']['carno']}，{temp4['data']['master']['billno']}"
            for n in temp4['data']['detail']:
                result.append({
                    'code': n['number'],
                    'whole_piece': n['wholepiece'],
                    'scatt_piece': n['scattpiece'],
                    'model': n['specification'],
                    'weight': n['saomaQty'],
                    'name': n['materialidName'],
                    'remark': remark
                })
        result = list(reversed(result))  # 倒置数组，因为默认排序是时间倒序列
        result = code_to_material_id(result)
        return result, page_1['data']['total']
    elif car_type_dict['废品销售'] == car_type_id:
        for m in sys_id_list:  # m 指的是
            temp4 = req_checklist_list_detail(token, m)
            j_weight: Decimal = Decimal(temp4['data']['master']['netWeight']).quantize(Decimal('0.001'))  # 净重
            if j_weight <= 100:  # 如果净重小于100千克，跳过
                continue
            # 默认只有一条明细，那就不需要匹重
            n = temp4['data']['detail'][0]
            result.append({
                'name': n['materialidName'],  # 规格
                'weight': j_weight,  # 净重
                'jjd_no': temp4['data']['master']['billno'],  # 检斤单号
                'car_no': temp4['data']['master']['carno'],  # 车号
                'customer_name': temp4['data']['master']['customerName'],  # 客户名称
                'bill_date': temp4['data']['master']['billdate'],  # 磅单日期
            })
        result = list(reversed(result))  # 倒置数组，因为默认排序是时间倒序列
        return result, page_1['data']['total']
    else:
        raise BusinessException(SCE.SERVER_ERR)
